#include "pipeline.h"

#include <cstdlib>
#include <memory>
#include <optional>
#include <regex>
#include <string>
#include <unordered_set>
#include <vector>

namespace cfg
{

/**
 * @brief 插值表达式解析与求值引擎
 *
 * 该类负责解析形如 `${...}` 或 `$VAR` 的占位符，将其替换为：
 * - ${VAR} 或 $VAR: 环境变量读取
 * - ${path.to.node}: 配置节点引用（支持数组索引）
 * - ${env:VAR:default}: 环境变量读取（含默认值）
 * - ${path.to.node:default}: 配置节点引用（含默认值）
 * - ${expr?condition:value_if_true:value_if_false}: 简单三元表达式
 *
 * 支持嵌套插值与循环引用检测。
 */
class InterpolationEngine
{
public:
    /**
     * @brief 对字符串进行插值解析和替换
     * @param input 待处理的字符串，可能包含插值占位符
     * @param config_view 当前配置视图，用于解析节点引用
     * @param out_errors 输出参数，用于收集解析过程中遇到的错误
     * @param visited_paths 输出参数，用于检测循环引用
     * @return 插值替换后的字符串
     */
    static std::string interpolate_string(const std::string & input,
                                          const View & config_view,
                                          std::vector<ConfigError> & out_errors,
                                          std::unordered_set<std::string> & visited_paths);

private:
    /**
     * @brief 解析单个插值表达式 ${...}
     * @param expr 待解析的插值表达式字符串
     * @param config_view 当前配置视图，用于解析节点引用
     * @param out_errors 输出参数，用于收集解析过程中遇到的错误
     * @param visited_paths 输出参数，用于检测循环引用
     * @return 解析后的字符串值（若成功），或空可选值（若解析失败）
     */
    static std::optional<std::string>
    resolve_expression(const std::string & expr,
                       const View & config_view,
                       std::vector<ConfigError> & out_errors,
                       std::unordered_set<std::string> & visited_paths);

    /**
     * @brief 解析环境变量引用
     * @param var_name 环境变量名
     * @param default_value 可选的默认值，若变量未定义则返回此值
     * @return 环境变量值（若存在），或默认值（若未定义）
     */
    static std::optional<std::string> resolve_env_var(const std::string & var_name,
                                                      const std::string & default_value = "");

    /**
     * @brief 解析配置节点引用
     * @param path 配置节点路径（支持数组索引）
     * @param config_view 当前配置视图，用于解析节点引用
     * @param default_value 可选的默认值，若节点不存在则返回此值
     * @param out_errors 输出参数，用于收集解析过程中遇到的错误
     * @param visited_paths 输出参数，用于检测循环引用
     * @return 节点值（若存在），或默认值（若不存在）
     */
    static std::optional<std::string>
    resolve_config_path(const std::string & path,
                        const View & config_view,
                        const std::string & default_value,
                        std::vector<ConfigError> & out_errors,
                        std::unordered_set<std::string> & visited_paths);

    /**
     * @brief 解析简单三元表达式
     * @param condition 条件表达式字符串
     * @param true_value 若条件为真时的返回值
     * @param false_value 若条件为假时的返回值
     * @param config_view 当前配置视图，用于解析表达式中的节点引用
     * @param out_errors 输出参数，用于收集解析过程中遇到的错误
     * @param visited_paths 输出参数，用于检测循环引用
     * @return 表达式结果（若成功），或空可选值（若解析失败）
     */
    static std::optional<std::string>
    resolve_ternary_expression(const std::string & condition,
                               const std::string & true_value,
                               const std::string & false_value,
                               const View & config_view,
                               std::vector<ConfigError> & out_errors,
                               std::unordered_set<std::string> & visited_paths);

    /**
     * @brief 将 Value 转换为字符串表示
     * @param view 配置视图，用于访问节点值
     * @return 节点值的字符串表示（若存在），或空字符串（若节点不存在）
     */
    static std::string value_to_string(const View & view);
};

std::string
InterpolationEngine::interpolate_string(const std::string & input,
                                        const View & config_view,
                                        std::vector<ConfigError> & out_errors,
                                        std::unordered_set<std::string> & visited_paths)
{
    // 作用：将字符串中的占位符替换为实际值，支持两种占位形式：
    // 1) ${...}：允许内部再次嵌套 ${...}，并支持三元表达式、路径、带默认值表达式等
    // 2) $VAR：等价于环境变量引用 env:VAR
    // 采用手写扫描实现，避免正则在遇到嵌套花括号时截断匹配导致表达式被拆分
    std::string result = input;

    size_t pos = 0;
    while (pos < result.size())
    {
        // 查找下一个 '$'
        size_t dollar_pos = result.find('$', pos);
        if (dollar_pos == std::string::npos)
        {
            break;
        }

        // 处理 ${...} 形式，占位符可以嵌套
        if (dollar_pos + 1 < result.size() && result[dollar_pos + 1] == '{')
        {
            size_t start = dollar_pos; // 指向 '$'
            size_t i = dollar_pos + 2; // 跳过 "${"
            int depth = 1;             // 当前花括号嵌套深度

            while (i < result.size() && depth > 0)
            {
                if (result[i] == '$' && (i + 1) < result.size() && result[i + 1] == '{')
                {
                    // 嵌套新的占位表达式
                    depth += 1;
                    i += 2;
                    continue;
                }
                else if (result[i] == '}')
                {
                    // 关闭一层占位表达式
                    depth -= 1;
                    i += 1;
                    continue;
                }
                else
                {
                    i += 1;
                }
            }

            if (depth != 0)
            {
                // 未找到匹配的 '}'，跳过当前字符继续扫描
                pos = dollar_pos + 1;
                continue;
            }

            size_t end = i - 1; // 指向匹配到的 '}'
            std::string expr = result.substr(start + 2, end - (start + 2));

            auto resolved = resolve_expression(expr, config_view, out_errors, visited_paths);
            if (resolved)
            {
                // 用解析结果替换整个占位符（包含外层 ${...}）
                result.replace(start, end - start + 1, *resolved);
                pos = start + resolved->length();
            }
            else
            {
                // 无法解析，跳过该占位符
                pos = end + 1;
            }

            continue;
        }

        // 处理 $VAR 形式（不带花括号），匹配变量名 [A-Za-z_][A-Za-z0-9_]*
        size_t name_start = dollar_pos + 1;
        if (name_start < result.size() &&
            ((result[name_start] >= 'A' && result[name_start] <= 'Z') ||
             (result[name_start] >= 'a' && result[name_start] <= 'z') || result[name_start] == '_'))
        {
            size_t j = name_start + 1;
            while (j < result.size())
            {
                char c = result[j];
                if ((c >= 'A' && c <= 'Z') || (c >= 'a' && c <= 'z') || (c >= '0' && c <= '9') ||
                    c == '_')
                {
                    ++j;
                }
                else
                {
                    break;
                }
            }

            std::string var_name = result.substr(name_start, j - name_start);
            auto resolved =
                resolve_expression("env:" + var_name, config_view, out_errors, visited_paths);
            if (resolved)
            {
                result.replace(dollar_pos, j - dollar_pos, *resolved);
                pos = dollar_pos + resolved->length();
            }
            else
            {
                pos = j;
            }

            continue;
        }

        // 非法或不可识别的 '$'，跳过该字符
        pos = dollar_pos + 1;
    }

    return result;
}

std::optional<std::string>
InterpolationEngine::resolve_expression(const std::string & expr,
                                        const View & config_view,
                                        std::vector<ConfigError> & out_errors,
                                        std::unordered_set<std::string> & visited_paths)
{
    // 解析三元表达式 condition?true_val:false_val
    std::regex ternary_regex(R"((.+?)\?(.+?):(.+))");
    std::smatch ternary_match;
    if (std::regex_match(expr, ternary_match, ternary_regex))
    {
        return resolve_ternary_expression(ternary_match[1].str(),
                                          ternary_match[2].str(),
                                          ternary_match[3].str(),
                                          config_view,
                                          out_errors,
                                          visited_paths);
    }

    // 优先处理环境变量引用，以免将 "env:" 前缀的冒号误认为默认值分隔符（C++17 兼容）
    if (expr.size() >= 4 && expr.compare(0, 4, "env:") == 0)
    {
        std::string var_name;
        std::string default_value;
        // 查找 "env:" 之后的下一个冒号，若存在则其后为默认值
        size_t second_colon = expr.find(':', 4);
        if (second_colon != std::string::npos)
        {
            var_name = expr.substr(4, second_colon - 4);
            default_value = expr.substr(second_colon + 1);
            // 默认值本身可能包含插值，占位符需要递归解析
            default_value =
                interpolate_string(default_value, config_view, out_errors, visited_paths);
        }
        else
        {
            var_name = expr.substr(4);
        }
        return resolve_env_var(var_name, default_value);
    }

    // 解析带默认值的表达式 expr:default（用于配置路径）
    size_t colon_pos = expr.find(':');
    std::string main_expr = expr;
    std::string default_value = "";

    if (colon_pos != std::string::npos)
    {
        main_expr = expr.substr(0, colon_pos);
        default_value = expr.substr(colon_pos + 1);
        // 默认值中可能再次包含插值
        default_value = interpolate_string(default_value, config_view, out_errors, visited_paths);
    }

    // 配置路径引用
    return resolve_config_path(main_expr, config_view, default_value, out_errors, visited_paths);
}

std::optional<std::string>
InterpolationEngine::resolve_env_var(const std::string & var_name,
                                     const std::string & default_value)
{
    const char * env_value = std::getenv(var_name.c_str());
    if (env_value != nullptr && env_value[0] != '\0')
    {
        return std::string(env_value);
    }

    if (!default_value.empty())
    {
        return default_value;
    }

    return std::nullopt;
}

std::optional<std::string>
InterpolationEngine::resolve_config_path(const std::string & path,
                                         const View & config_view,
                                         const std::string & default_value,
                                         std::vector<ConfigError> & out_errors,
                                         std::unordered_set<std::string> & visited_paths)
{
    // 检测循环引用
    if (visited_paths.count(path))
    {
        out_errors.push_back(ConfigError{
            Errc::Other, "circular reference detected in interpolation: " + path, {path}});
        return std::nullopt;
    }

    visited_paths.insert(path);

    // 查找配置节点
    auto node = config_view.lookup(path);
    if (!node)
    {
        visited_paths.erase(path);
        if (!default_value.empty())
        {
            return default_value;
        }
        out_errors.push_back(
            ConfigError{Errc::MissingKey, "interpolation path not found: " + path, {path}});
        return std::nullopt;
    }

    std::string result = value_to_string(*node);

    // 如果解析出的值仍包含插值表达式，递归解析
    if (result.find('$') != std::string::npos)
    {
        result = interpolate_string(result, config_view, out_errors, visited_paths);
    }

    visited_paths.erase(path);
    return result;
}

std::optional<std::string>
InterpolationEngine::resolve_ternary_expression(const std::string & condition,
                                                const std::string & true_value,
                                                const std::string & false_value,
                                                const View & config_view,
                                                std::vector<ConfigError> & out_errors,
                                                std::unordered_set<std::string> & visited_paths)
{
    // 简单条件评估：检查环境变量或配置路径是否存在且非空
    bool condition_result = false;

    if (condition.size() >= 4 && condition.compare(0, 4, "env:") == 0)
    {
        std::string var_name = condition.substr(4);
        const char * env_value = std::getenv(var_name.c_str());
        condition_result = (env_value != nullptr && env_value[0] != '\0');
    }
    else
    {
        auto node = config_view.lookup(condition);
        if (node)
        {
            // 检查节点是否存在且非 null
            condition_result = !node->is_null();
            if (condition_result)
            {
                // 进一步检查字符串值是否非空
                auto str_val = node->get_string();
                if (str_val && str_val->empty())
                {
                    condition_result = false;
                }
            }
        }
    }

    std::string result = condition_result ? true_value : false_value;
    // 递归处理选择的值中的插值
    return interpolate_string(result, config_view, out_errors, visited_paths);
}

std::string
InterpolationEngine::value_to_string(const View & view)
{
    // 尝试获取字符串值
    auto str_val = view.get_string();
    if (str_val)
    {
        return *str_val;
    }

    // 尝试获取数值
    auto int_val = view.get_int64();
    if (int_val)
    {
        return std::to_string(*int_val);
    }

    auto double_val = view.get_number();
    if (double_val)
    {
        return std::to_string(*double_val);
    }

    // 尝试获取布尔值
    auto bool_val = view.get_bool();
    if (bool_val)
    {
        return *bool_val ? "true" : "false";
    }

    // 空值
    if (view.is_null())
    {
        return "";
    }

    // 其他类型返回类型标识
    auto type = view.value_type();
    if (type)
    {
        switch (*type)
        {
            case SchemaValueType::Array:
                return "[array]";
            case SchemaValueType::Object:
                return "[object]";
            default:
                return "[unknown]";
        }
    }

    return "[unknown]";
}

/**
 * @brief 插值 Transformer 插件
 * @details 该插件负责解析并替换配置中的 `${...}` 或 `$VAR` 占位符，支持：
 * - 环境变量值（支持默认值）
 * - 配置节点值（支持路径与默认值）
 * - 三元表达式结果
 *
 * 支持嵌套插值与循环引用检测。
 */
class TransformerInterpolate : public ITransformer
{
public:
    /**
     * @brief 对 Builder 中的配置执行插值替换
     *
     * 该函数会遍历整个配置树，将所有包含 `${...}` 或 `$VAR` 占位符的字符串
     * 替换为对应的环境变量值、配置节点值或三元表达式结果。
     *
     * @param builder       可写配置构建器，用于就地更新插值后的值
     * @param options       插件选项，支持 `enabled` 和 `max_depth` 等参数
     * @param out_errors    输出参数，用于收集解析过程中产生的错误
     * @return true  插值成功（即使某些占位符解析失败也视为成功，错误已写入 out_errors）
     * @return false 插件选项校验失败或配置冻结失败
     */
    bool transform(Builder & builder,
                   const PluginOptions & options,
                   std::vector<ConfigError> & out_errors) override;

private:
    /**
     * @brief 递归遍历配置节点并对字符串叶子执行插值
     *
     * 遇到对象或数组时继续向下递归；遇到字符串且包含 `$` 时调用 InterpolationEngine
     * 进行替换，并通过 builder.set() 写回新值。
     *
     * @param builder       可写配置构建器，用于更新插值后的字符串
     * @param node_view     当前节点的只读视图
     * @param current_path  当前节点在配置树中的路径，用于 builder.set() 定位
     * @param out_errors    输出参数，用于收集插值过程中产生的错误
     * @param root_view     整棵配置树的只读视图，供 InterpolationEngine 解析路径引用
     */
    void traverse_and_interpolate(Builder & builder,
                                  const View & node_view,
                                  const std::string & current_path,
                                  std::vector<ConfigError> & out_errors,
                                  const View & root_view);
};

bool
TransformerInterpolate::transform(Builder & builder,
                                  const PluginOptions & options,
                                  std::vector<ConfigError> & out_errors)
{
    plugin::PluginOptionsChecker checker("interpolate", options);

    // 定义选项规范（当前实现未使用 max_depth，但保留接口以便后续扩展）
    checker.add_spec({.name = "enabled",
                      .required = false,
                      .enum_values = {"true", "false"},
                      .description = "启用或禁用插值功能",
                      .default_value = "true"});

    checker.add_spec({.name = "max_depth",
                      .required = false,
                      .enum_values = {},
                      .description = "最大递归深度，防止无限递归",
                      .default_value = "10"});

    if (!checker.validate(out_errors))
    {
        return false;
    }

    auto enabled = checker.get_string("enabled", "true");
    if (!enabled || *enabled == "false")
    {
        return true; // 禁用时直接返回
    }

    // 冻结快照以创建只读视图（避免直接访问 Builder 的私有成员）
    auto frozen = builder.freeze();
    if (!frozen)
    {
        // 将冻结失败的错误并入 out_errors，并终止本次插值（随后流水线的 freeze 仍会处理这些错误）
        for (const auto & e : frozen.error())
            out_errors.push_back(e);
        return false;
    }

    View root_view(*frozen);

    // 从根开始遍历
    traverse_and_interpolate(builder, root_view, std::string{}, out_errors, root_view);
    return true;
}

void
TransformerInterpolate::traverse_and_interpolate(Builder & builder,
                                                 const View & node_view,
                                                 const std::string & current_path,
                                                 std::vector<ConfigError> & out_errors,
                                                 const View & root_view)
{
    // 对象分支：枚举条目并递归
    if (auto ov = node_view.object_view())
    {
        if (*ov)
        {
            // C++17 兼容：不依赖 ranges 视图，直接遍历 props
            for (const auto & kv : (**ov).props)
            {
                std::string_view key_sv(kv.first);
                const Value & v = kv.second;

                std::string key_str(kv.first);
                std::string child_path =
                    current_path.empty() ? key_str : current_path + "." + key_str;

                // 对象子节点：递归
                if (std::holds_alternative<std::shared_ptr<const Object>>(v))
                {
                    auto child_view = node_view.subobj(key_sv);
                    if (child_view)
                    {
                        traverse_and_interpolate(
                            builder, *child_view, child_path, out_errors, root_view);
                    }
                    continue;
                }

                // 数组子节点：遍历数组元素
                if (std::holds_alternative<std::shared_ptr<const Array>>(v))
                {
                    auto child_view = node_view.subobj(key_sv);
                    if (child_view)
                    {
                        auto av = child_view->array_view();
                        if (av)
                        {
                            for (size_t i = 0; i < av->size(); ++i)
                            {
                                auto item_view = child_view->at(i);
                                if (item_view)
                                {
                                    traverse_and_interpolate(builder,
                                                             *item_view,
                                                             child_path + "[" + std::to_string(i) +
                                                                 "]",
                                                             out_errors,
                                                             root_view);
                                }
                            }
                        }
                    }
                    continue;
                }

                // 叶子字符串：尝试插值
                if (auto sp = std::get_if<std::string>(&v))
                {
                    if (sp->find('$') != std::string::npos)
                    {
                        std::unordered_set<std::string> visited;
                        std::string replaced = InterpolationEngine::interpolate_string(
                            *sp, root_view, out_errors, visited);
                        if (replaced != *sp)
                        {
                            builder.set(child_path, replaced);
                        }
                    }
                }
            }
        }
        return;
    }

    // 数组分支：按索引递归
    if (auto av = node_view.array_view())
    {
        for (size_t i = 0; i < av->size(); ++i)
        {
            auto item_view = node_view.at(i);
            if (item_view)
            {
                std::string child_path = current_path + "[" + std::to_string(i) + "]";
                traverse_and_interpolate(builder, *item_view, child_path, out_errors, root_view);
            }
        }
        return;
    }

    // 叶子：若为字符串则尝试插值
    auto s = node_view.get_string();
    if (s && s->find('$') != std::string::npos)
    {
        std::unordered_set<std::string> visited;
        std::string replaced =
            InterpolationEngine::interpolate_string(*s, root_view, out_errors, visited);
        if (replaced != *s)
        {
            if (!current_path.empty())
            {
                builder.set(current_path, replaced);
            }
        }
    }
}

} // namespace cfg

// 注册插件
namespace cfg
{
REGISTER_TRANSFORMER("interpolate", TransformerInterpolate)
}